package yxy.apple.util;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

public class IPV4Utility {

	public static byte[] toBytes(String ip) {
		String[] items = ip.split("\\.");
		byte[] result = new byte[4];
		for (int i = 0; i < items.length; i++) {
			byte value = NumberUtility.parseByte(items[i], (byte) 0x0);
			result[i] = value;
		}
		return result;
	}

	public static int toInteger(String ip) {
		byte[] values = toBytes(ip);
		int value = 0x0;
		value = value | ((values[0] & 0x000000FF) << 24);
		value = value | ((values[1] & 0x000000FF) << 16);
		value = value | ((values[2] & 0x000000FF) << 8);
		value = value | (values[3] & 0x000000FF);
		return value;
	}

	public static int toInteger(InetAddress ip) {
		byte[] values = ip.getAddress();
		int value = 0x0;
		value = value | ((values[0] & 0x000000FF) << 24);
		value = value | ((values[1] & 0x000000FF) << 16);
		value = value | ((values[2] & 0x000000FF) << 8);
		value = value | (values[3] & 0x000000FF);
		return value;
	}

	public static String toString(int ip) {
		StringBuffer buffer = new StringBuffer();
		buffer.append((ip & 0xFF000000) >>> 24);
		buffer.append(".");
		buffer.append((ip & 0x00FF0000) >>> 16);
		buffer.append(".");
		buffer.append((ip & 0x0000FF00) >>> 8);
		buffer.append(".");
		buffer.append(ip & 0x000000FF);
		return buffer.toString();
	}

	public static String toString(InetAddress address) {
		StringBuffer buffer = new StringBuffer();
		byte[] bytes = address.getAddress();
		buffer.append(bytes[0] & 0x000000FF);
		buffer.append(".");
		buffer.append(bytes[1] & 0x000000FF);
		buffer.append(".");
		buffer.append(bytes[2] & 0x000000FF);
		buffer.append(".");
		buffer.append(bytes[3] & 0x000000FF);
		return buffer.toString();
	}

	public static InetAddress getLocalInetAddress(String name) throws IOException {
		InetAddress result = null;
		Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
		while (interfaces.hasMoreElements()) {
			NetworkInterface nif = interfaces.nextElement();
			if (nif.getDisplayName().equalsIgnoreCase(name) || nif.getName().equalsIgnoreCase(name)) {
				Enumeration<InetAddress> addresses = nif.getInetAddresses();
				while (addresses.hasMoreElements()) {
					InetAddress address = addresses.nextElement();
					if (!address.isLinkLocalAddress() && !address.isLoopbackAddress()) {
						result = address;
						break;
					}
				}
			}
			if (result != null) {
				break;
			}
		}
		return result;
	}
	public static boolean isInRange(String network, String mask) {
		String[] networkips = network.split("\\.");
		int ipAddr = (Integer.parseInt(networkips[0]) << 24)
				| (Integer.parseInt(networkips[1]) << 16)
				| (Integer.parseInt(networkips[2]) << 8)
				| Integer.parseInt(networkips[3]);
		int type = Integer.parseInt(mask.replaceAll(".*/", ""));
		int mask1 = 0xFFFFFFFF << (32 - type);
		String maskIp = mask.replaceAll("/.*", "");
		String[] maskIps = maskIp.split("\\.");
		int cidrIpAddr = (Integer.parseInt(maskIps[0]) << 24)
				| (Integer.parseInt(maskIps[1]) << 16)
				| (Integer.parseInt(maskIps[2]) << 8)
				| Integer.parseInt(maskIps[3]);

		return (ipAddr & mask1) == (cidrIpAddr & mask1);
	}

	public static boolean ipIsInNet(String iparea, String ip) {
		if (iparea == null)
			throw new NullPointerException("IP段不能为空！");
		if (ip == null)
			throw new NullPointerException("IP不能为空！");
		iparea = iparea.trim();
		ip = ip.trim();
		final String REGX_IP = "((25[0-5]|2[0-4]//d|1//d{2}|[1-9]//d|//d)//.){3}(25[0-5]|2[0-4]//d|1//d{2}|[1-9]//d|//d)";
		final String REGX_IPB = REGX_IP + "//-" + REGX_IP;
		if (!iparea.matches(REGX_IPB) || !ip.matches(REGX_IP))
			return false;
		int idx = iparea.indexOf('-');
		String[] sips = iparea.substring(0, idx).split("//.");
		String[] sipe = iparea.substring(idx + 1).split("//.");
		String[] sipt = ip.split("//.");
		long ips = 0L, ipe = 0L, ipt = 0L;
		for (int i = 0; i < 4; ++i) {
			ips = ips << 8 | Integer.parseInt(sips[i]);
			ipe = ipe << 8 | Integer.parseInt(sipe[i]);
			ipt = ipt << 8 | Integer.parseInt(sipt[i]);
		}
		if (ips > ipe) {
			long t = ips;
			ips = ipe;
			ipe = t;
		}
		return ips <= ipt && ipt <= ipe;
	}
}
